最近学了一段时间的 java web 后台,所学内容主要为网上视频,以及《深入分析 java web 技术内幕》一书,先总结一下 XML 和 tomcat 内容。

XML

Xml 文件解读

关于XML文档的xmlns、xmlns:xsi和xsi:schemaLocation
xmlns表示默认的Namespace。
xmlns:xsi表示使用xsi作为前缀的Namespace,当然前缀xsi需要在文档中声明。
来自 https://my.oschina.net/itblog/blog/390001

标签

一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如:

<input name=“text”>

属性值一定要用双引号(”)或单引号(’)引起来
定义属性必须遵循与标签相同的命名规范
多学一招:在XML技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述,例如:

<input>
        <name>text</name>
</input>

处理指令

处理指令,简称PI (processing instruction)。处理指令用来指挥解析引擎如何解析XML文档内容。

例如,在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容。

<?xml-stylesheet type="text/css" href="1.css"?>

处理指令必须以“<?”作为开头,以“?>”作为结尾,XML声明语句就是最常见的一种处理指令。

XML 约束

在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。
常用的约束技术

XML DTD 
XML Schema

XML DTD

XML文件使用 DOCTYPE 声明语句来指明它所遵循的DTD文件,DOCTYPE声明语句有两种形式:

当引用的文件在本地时,采用如下方式:

<!DOCTYPE 文档根结点 SYSTEM "DTD文件的URL">

例如:

<!DOCTYPE 书架 SYSTEM “book.dtd”>。

当引用的文件是一个公共的文件时,采用如下方式:

<!DOCTYPE 文档根结点 PUBLIC "DTD名称" "DTD文件的URL">

例如:

<!DOCTYPE web-app PUBLIC 
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

XML Schema

XML Schema 也是一种用于定义和描述 XML 文档结构与内容的模式语言,其出现是为了克服 DTD 的局限性

XML Schema VS DTD:

XML Schema符合XML语法结构。 
DOM、SAX等XML API很容易解析出XML Schema文档中的内容。 
XML Schema对名称空间支持得非常好。 
XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型。 
XML Schema定义约束的能力非常强大,可以对XML实例文档作出细致的语义限制。
XML Schema不能像DTD一样定义实体,比DTD更复杂,但Xml Schema现在已是w3c组织的标准,它正逐步取代DTD。  

XML 解析

XML 解析方式分为两种:dom 和 sax

dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。
sax: (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。

XML解析器

Crimson、Xerces 、Aelfred2

XML解析开发包

Jaxp、Jdom、dom4j

JAXP

JAXP 开发包是J2SE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成
在 javax.xml.parsers 包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对xml文档进行解析的 DOM 或 SAX 的解析器对象。

DOM

javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 ,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。

调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。

调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。

调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,进行可以利用DOM特性对整个XML文档进行操作了。

SAX

在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。

SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。

SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。

SAX 解析 XML 步骤
使用SAXParserFactory创建SAX解析工厂

SAXParserFactory spf = SAXParserFactory.newInstance();

通过SAX解析工厂得到解析器对象

SAXParser sp = spf.newSAXParser();

通过解析器对象得到一个XML的读取器

XMLReader xmlReader = sp.getXMLReader();

设置读取器的事件处理器

xmlReader.setContentHandler(new BookParserHandler());

解析xml文件

xmlReader.parse("book.xml");

其他三种解析工具就不一一写了,以后用到再学习。

其实还有一种解析 xml 的方式:digester。tomcat就是用的这一种方式。
请见: https://www.ibm.com/developerworks/cn/xml/dm-1208gub/index.html

tomcat

tomcat 版本和源码都是 apache-tomcat-9.0.0.M21

tomcat 容器模型

tomcat 以远程调试模式启动

参考网页:
https://blogs.mulesoft.com/dev/tomcat-tcat-server/debugging-your-tomcat-webapp-with-eclipse/
http://blog.trifork.com/2014/07/14/how-to-remotely-debug-application-running-on-tomcat-from-within-intellij-idea/

较新的版本

方法一:命令行中输入

JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n"
catalina.sh jpda start

其实直接输入 catalina.bat jpda 带的默认参数和上面是一样的。要想改变默认参数,CMD 中输入如下:

export JPDA_ADDRESS="8080"

其他参数修改:
JPDA_TRANSPORT: to specify JPDA transport used
JPDA_ADDRESS: to specify port for remote debugging
JPDA_SUSPEND: to specify if to suspend JVM after startup

方法二:修改 catalina.bat 文件

旧版本

方法一:命令行中输入

Set  “CATALINA_OPTS=-Xdebug  -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
catalina.bat jpda

方法二:修改 catalina.bat 文件

参考网页:http://www.cnblogs.com/doit8791/p/5479645.html

添加:Set  “CATALINA_OPTS=-Xdebug  -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"  
命令行窗口下输入:
set JPDA_ADDRESS=8777(调试端口) 
catalina.bat jpda start

参数说明:

-Xdebug                              : 启用调试模式

-Xrunjdwp<sub-options>  : 加载JVM的JPDA参考实现库

transport=dt_socket           :Socket连接,可选dt_shmem 通过共享内存的方式连接到调试服务器

address=8000                     :调试服务器监听的端口

server=y                             : 是否是服务器端,n为客户端

suspend=n                         : 启动过程是否加载暂停,y为启动时暂停,方便调试启动过程

启动过程

类图和时序图如下:

server.xml文件的加载

因为自己想看一下 tomcat 启动时各种属性是怎么注入的,所以设置 JPDA_SUSPEND=”y”,然后再执行 catalina.bat jpda start

因为刚刚学了 XML 文件的解析,就分析了一下启动过程中 tomacat 是如何解析 server.xml 文件的。

自己画的类图和时序图如下:

时序图只画到了调用 startElement 函数,因为 SAX 采用事件处理的方式解析 XML 文件,自己想看看这个过程是如何完成的。

参考网页:
tomcat源码和启动过程
Tomcat 启动过程

Tomcat 类加载机制

源代码中 Bootstrap main 方法调用自己的 init 方法,init 方法再调用自己的 initClassLoaders 方法,此方法内容如下,可以看出 tomcat 的类加载器有三个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void initClassLoaders() {
try {
commonLoader = createClassLoader("common", null);
if( commonLoader == null ) {
// no config file, default to this loader - we might be in a 'single' env.
commonLoader=this.getClass().getClassLoader();
}
catalinaLoader = createClassLoader("server", commonLoader);
sharedLoader = createClassLoader("shared", commonLoader);
} catch (Throwable t) {
handleThrowable(t);
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}

参考网页:
http://www.cnblogs.com/xing901022/p/4574961.html

tomcat生命周期的管理——生命周期统一接口Lifecycle

《深入分析 java web》一书中第11章讲的很详细,参考网页中最下面的讲的也很详细。

有一点要注意的是,自己查看的源码版本比较新,已经舍弃了 lifecyclesupport 类,listener 都是直接注册到的各个容器中了的,没有再经过统一管理。

参考网页:
http://blog.csdn.net/wangyangzhizhou/article/details/40793663
http://uule.iteye.com/blog/2340873
http://www.cnblogs.com/jiaan-geng/p/4864501.html讲的特别好

本文总阅读量次.

留言